<?php

declare(strict_types=1);

namespace app\system\controller;

use app\admin\BaseAdminController;
use think\facade\View;
use app\system\model\Role as RoleModel;
use think\facade\Request;
use app\system\model\LogOperate as Log;
use app\system\model\RoleDept;
use app\system\model\RoleMenu;
use app\system\model\Dept;
use think\helper\Str;

class Role extends BaseAdminController
{
    /**
     * 用于标记不同的数据ID
     * @var int
     */
    private $plus = 0;

    /**
     * 角色管理页面
     */
    public function index()
    {
        View::assign('title', '角色管理/系统管理');
        View::assign('dataScope', RoleModel::dataScope());
        return View::fetch();
    }

    /**
     * 读取角色信息列表
     */
    public function data()
    {
        $obj = new RoleModel();
        $list = $obj->order(['sort' => 'asc', 'id' => 'desc'])->select();
        $new = [];
        $arr = RoleModel::dataScope();
        $new[] = [
            'id' => 0,
            'name' => '超级管理员',
            'data_scope' => $arr[1],
            'scope_id' => 1,
            'sort' => 0,
            'update_time' => date('Y-m-d H:i:s'),
            'status' => 0,
        ];
        foreach ($list as $value) {
            $new[] = [
                'id' => $value['id'],
                'name' => $value['name'],
                'data_scope' => $arr[$value['data_scope']],
                'scope_id' => $value['data_scope'],
                'sort' => $value['sort'],
                'update_time' => $value['update_time'],
                'status' => $value['status'],
            ];
        }
        return json($new);
    }

    /**
     * 保存角色信息
     */
    public function save()
    {
        if ($this->envMode == 'demo'){
            return $this->isDemo();
        }
        $id = input('id/d', 0);
        $data_scope = input('dataScope/d', 0);
        $name = input('name');
        $sort = input('sort/d', 0);
        if ($id) {
            $title = '编辑角色';
            $obj = RoleModel::find($id);
        } else {
            $title = '新增角色';
            $obj = new RoleModel;
        }
        $obj->data_scope = $data_scope;
        $obj->name = $name;
        $obj->sort = $sort;
        $obj->update_by = USERNAME;
        $obj->save();
        $arr = RoleModel::dataScope();
        Log::add($title, [
            'ID' => $obj->id,
            '角色名称' => $name,
            '显示顺序' => $sort,
            '数据权限' => $arr[$data_scope],
        ]);
        return json(['msg' => '']);
    }

    /**
     * 删除角色信息
     */
    public function remove()
    {
        if ($this->envMode == 'demo'){
            return $this->isDemo();
        }
        $id = input('id/d', 0);
        $obj = RoleModel::find($id);
        $obj->delete();
        $arr = RoleModel::dataScope();
        Log::add('删除角色', [
            'ID' => $id,
            '角色名称' => $obj->name,
            '显示顺序' => $obj->sort,
            '数据权限' => $arr[$obj->data_scope],
        ]);
        // 删除菜单与数据权限
        RoleDept::destroy(function($query) use ($id){
            $query->where('role_id', $id);
        });
        RoleMenu::destroy(function($query) use ($id){
            $query->where('role_id', $id);
        });
        return json(['msg' => '']);
    }

    /**
     * 查看角色信息
     */
    public function view()
    {
        $id = input('id/d', 0);
        $obj = RoleModel::find($id);
        return json($obj);
    }

    /**
     * 角色状态变更
     */
    public function status()
    {
        if ($this->envMode == 'demo'){
            return $this->isDemo();
        }
        $id = input('id/d', 0);
        $obj = RoleModel::find($id);
        $status = $obj->status ? '正常' : '停用';
        $obj->status = $obj->status ? 0 : 1;
        $obj->update_by = USERNAME;
        $obj->save();
        Log::add('角色状态', [
            'ID' => $id,
            '角色名称' => $obj->name,
            '状态' => $status,
        ]);
        return json(['msg' => '']);
    }

    /**
     * 设置角色后台可见菜单权限
     */
    public function menu()
    {
        if (Request::isAjax()) {
            if ($this->envMode == 'demo'){
                return $this->isDemo();
            }
            $id = input('id/d', 0);
            $arr = input('arr/a', []);
            RoleMenu::destroy(function($query) use ($id){
                $query->where('role_id', $id);
            });
            $obj = new RoleMenu;
            $data = [];
            $as = [];
            $bs = [];
            foreach ($arr as $value) {
                $ex = explode('/', $value);
                $as[] = $ex[0] . '/' . $ex[1];
                $bs[] = $ex[0] . '/' . $ex[1] . '/' . $ex[2];
            }
            $as = array_unique($as);
            foreach ($as as $value) { // 这里是为了菜单 index 可见
                $ac = $value . '/index';
                if (!in_array($ac, $bs)) {
                    $bs[] = $ac;
                }
            }
            foreach ($bs as $value) {
                $data[] = [
                    'role_id' => $id,
                    'role_name' => $value,
                ];
            }
            $obj->saveAll($data);
            return json([]);
        }
        View::assign('title', '设置菜单权限/角色管理/系统管理');
        $obj = $this->getRole();
        // 读取所有菜单
        $dir = base_path();
        $handle = opendir($dir);
        $menus = [];
        $methods = [];
        while (false !== ($entry = readdir($handle))) {
            if ($entry != "." && $entry != "..") {
                $filePath = $dir . $entry;
                if (is_dir($filePath)) {
                    $menuFile = $filePath . '/config/menu.php';
                    $lockFile = $filePath . '/config/delete.lock'; // 存在时则为删除状态
                    if (!file_exists($lockFile) && file_exists($menuFile)) {
                        $menu = require $menuFile;
                        if ($menu['show']) {
                            $menus[$menu['name']] = $menu;
                            if (isset($menu['methods'])) {
                                $methods[$menu['name']] = $menu['methods'];
                            }
                        }
                    }
                }
            }
        }
        // 生成菜单 
        $selected = RoleMenu::where('role_id', $obj->id)->column('role_name');
        $new = $this->getActions($menus, $methods, $selected);
        View::assign('tree', json_encode($new, 256));
        View::assign('addJs', addJs(['jstree']));
        return View::fetch();
    }

    /**
     * 格式化菜单权限数据
     * @param $url 控制器方法完整路径
     * @param $methods 控制器方法合集
     * @param $selected 已选权限
     */
    private function getMethods($url, $methods, $selected)
    {
        $actions = [];
        $ex = explode('/', $url);
        $app = $ex[0];
        $controller = $ex[1];
        if (isset($methods[$app][$controller])) {
            $items = $methods[$app][$controller];
            foreach ($items as $name => $item) {
                $this->plus++;
                $state = [];
                if ($selected && in_array($app . '/' . $controller . '/' . $name, $selected)) {
                    $state['selected'] = 'true';
                }
                $actions[] = [
                    'id' => $app . '/' . $controller . '/' . $name . '/' . $this->plus,
                    'text' => $item,
                    'state' => $state,
                    'children' => [],
                    'icon' => 'mdi mdi-file-outline',
                ];
            }
        }
        return $actions;
    }

    /**
     * 格式化菜单权限数据
     * @param $arr 菜单数据
     * @param $methods 控制器方法合集
     * @param $selected 已选权限
     */
    private function getActions($arr, $methods, $selected)
    {
        $new = [];
        foreach ($arr as $value) {
            $this->plus++;
            $value['name'] = Str::contains($value['name'], '/') ? $value['name'] : $value['name'] . '/index/index';
            $state = [];
            if ($selected && in_array($value['name'], $selected)) {
                $state['selected'] = 'true';
            }
            $children = isset($value['children']) && $value['children'] ? $this->getActions($value['children'], $methods, $selected) : $this->getMethods($value['name'], $methods, $selected);
            $new[] = [
                'id' => $value['name'] . '/' . $this->plus,
                'text' => $value['title'],
                'state' => $children ? [] : $state, // 让父级不选中
                'children' => $children,
                'icon' => $children ? 'mdi mdi-folder-outline' : 'mdi mdi-file-outline',
            ];
        }
        return $new;
    }

    /**
     * 读取角色数据权限信息
     */
    private function getRole()
    {
        $id = input('id/d', 0);
        $obj = RoleModel::find($id);
        View::assign('role', $obj);
        return $obj;
    }

    /**
     * 设置数据权限页面
     */
    public function dept()
    {
        if (Request::isAjax()) {
            if ($this->envMode == 'demo'){
                return $this->isDemo();
            }
            $id = input('id/d', 0);
            $arr = input('arr/a', []);
            RoleDept::destroy(function($query) use ($id){
                $query->where('role_id', $id);
            });
            $obj = new RoleDept;
            $data = [];
            foreach ($arr as $value) {
                $data[] = [
                    'role_id' => $id,
                    'dept_id' => $value,
                ];
            }
            $obj->saveAll($data);
            return json([]);
        }
        View::assign('title', '设置数据权限/角色管理/系统管理');
        $obj = $this->getRole();
        $selected = RoleDept::where('role_id', $obj->id)->column('dept_id');
        View::assign('tree', json_encode(Dept::getTrees($selected), 256));
        View::assign('addJs', addJs(['jstree']));
        return View::fetch();
    }
}
